#include "getwidproc.h"

///< 枚举窗口回调函数
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) {
  EnumWindowsArg *pArg = (EnumWindowsArg *)lParam;
  DWORD dwProcessID = 0;
  // 通过窗口句柄取得进程ID
  ::GetWindowThreadProcessId(hwnd, &dwProcessID);
  if (dwProcessID == pArg->dwProcessID) {
    pArg->hwndWindow = hwnd;
    // 找到了返回FALSE
    return FALSE;
  }
  // 没找到，继续找，返回TRUE
  return TRUE;
}
///< 通过进程ID获取窗口句柄
HWND GetWindowHwndByPID(DWORD dwProcessID) {
  HWND hwndRet = NULL;
  EnumWindowsArg ewa;
  ewa.dwProcessID = dwProcessID;
  ewa.hwndWindow = NULL;
  EnumWindows(EnumWindowsProc, (LPARAM)&ewa);
  if (ewa.hwndWindow) {
    hwndRet = ewa.hwndWindow;
  }
  return hwndRet;
}

std::string WcharToChar(const wchar_t *wp, size_t m_encode = CP_ACP) {
  std::string str;
  int len =
      WideCharToMultiByte(m_encode, 0, wp, wcslen(wp), NULL, 0, NULL, NULL);
  char *m_char = new char[len + 1];
  WideCharToMultiByte(m_encode, 0, wp, wcslen(wp), m_char, len, NULL, NULL);
  m_char[len] = '\0';
  str = m_char;
  delete[] m_char;
  return str;
}

DWORD findProcess(std::string name) {
  DWORD hRet = 0;
  PROCESSENTRY32 pe;
  HANDLE hProceessnap;
  bool bPorcess = false;
  std::string procName;
  do {
    pe.dwSize = sizeof(pe);
    hProceessnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hProceessnap == INVALID_HANDLE_VALUE)
      break;

    bPorcess = Process32First(hProceessnap, &pe);
    while (bPorcess) {
      procName = WcharToChar(pe.szExeFile);
      if (0 == procName.compare(name)) {
        // logDebug("name:%s\t\tID:%lu\n", procName.c_str(), pe.th32ProcessID);
        hRet = pe.th32ProcessID;
        break;
      }
      bPorcess = Process32Next(hProceessnap, &pe);
    }

    CloseHandle(hProceessnap);
  } while (0);

  return hRet;
}

HWND findHwndByName(std::string procName) {
  DWORD procId = 0;
  HWND hRet = 0;

  do {
    procId = findProcess(procName);
    if (procId == 0)
      break;

    hRet = GetWindowHwndByPID(procId);
  } while (0);

  return hRet;
}

int GetWindowTextSafe(HWND hWnd, LPTSTR lpString, int nMaxCount) {
  if (NULL == hWnd || FALSE == IsWindow(hWnd) || NULL == lpString ||
      0 == nMaxCount) {
    return GetWindowText(hWnd, lpString, nMaxCount);
  }
  DWORD dwHwndProcessID = 0;
  DWORD dwHwndThreadID = 0;
  dwHwndThreadID = GetWindowThreadProcessId(
      hWnd, &dwHwndProcessID); //获取窗口所属的进程和线程ID

  //窗口进程不是当前调用进程时，返回原本调用
  if (dwHwndProcessID != GetCurrentProcessId()) {
    return GetWindowText(hWnd, lpString, nMaxCount);
  }

  //窗口进程是当前进程时：
  if (dwHwndThreadID == GetCurrentThreadId()) {
    //窗口线程就是当前调用线程，返回原本调用
    return GetWindowText(hWnd, lpString, nMaxCount);
  }

#ifndef _UNICODE
  WCHAR *lpStringUnicode = new WCHAR[nMaxCount];
  InternalGetWindowText(hWnd, lpStringUnicode, nMaxCount);
  int size =
      WideCharToMultiByte(CP_ACP, 0, lpStringUnicode, -1, NULL, 0, NULL, NULL);
  if (size <= nMaxCount) {
    size = WideCharToMultiByte(CP_ACP, 0, lpStringUnicode, -1, lpString, size,
                               NULL, NULL);
    if (NULL != lpStringUnicode) {
      delete[] lpStringUnicode;
      lpStringUnicode = NULL;
    }
    return size;
  }
  if (NULL != lpStringUnicode) {
    delete[] lpStringUnicode;
    lpStringUnicode = NULL;
  }
  return 0;

#else
  return InternalGetWindowText(hWnd, lpString, nMaxCount);
#endif
}

HWND findHwndByTitle(std::string procName, std::string title) {
  DWORD procId = 0;
  HWND hRet = 0;
  HWND deskId = 0;
  int len = 0;
  char str[200] = {0};
  do {
    procId = findProcess(procName);
    if (procId == 0)
      break;
    deskId = GetDesktopWindow();
    while (deskId != NULL) {
      len = GetWindowTextSafe(deskId, (LPTSTR)str, 200);
      if (0 != len) {
        if (0 == strcmp(str, title.c_str())) {
          hRet = deskId;
          break;
        }
      }
      deskId = GetNextWindow(deskId, GW_HWNDNEXT);
    }

  } while (0);

  return hRet;
}
